package com.forum.auth.controller;

import com.forum.auth.feign.UserServiceClient;
import com.forum.auth.model.LoginRequest;
import com.forum.auth.model.RegisterRequest;
import com.forum.auth.model.TokenInfo;
import com.forum.auth.model.UserDTO;
import com.forum.auth.util.JwtUtil;
import com.forum.common.exception.BusinessException;
import com.forum.common.response.Result;
import com.forum.common.response.ResultCode;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * 认证控制器
 */
@Slf4j
@RestController
@RequiredArgsConstructor
public class AuthController {
    
    private final UserServiceClient userServiceClient;
    private final JwtUtil jwtUtil;
    
    /**
     * 登录
     *
     * @param loginRequest 登录请求
     * @return 令牌信息
     */
    @PostMapping("/login")
    public Result<TokenInfo> login(@Valid @RequestBody LoginRequest loginRequest) {
        log.info("用户登录请求: {}", loginRequest.getUsername());
        
        // 用户名和密码认证
        Long userId = userServiceClient.validateCredentials(
                loginRequest.getUsername(), 
                loginRequest.getPassword()
        );
        
        if (userId == null) {
            log.warn("登录失败，用户名或密码错误: {}", loginRequest.getUsername());
            throw new BusinessException(ResultCode.LOGIN_ERROR);
        }
        
        log.info("用户验证成功: {}, userId: {}", loginRequest.getUsername(), userId);
        
        // 获取用户详情
        UserDTO userDetails = userServiceClient.getUserDetails(userId);
        
        // 从用户详情中获取角色信息
        String role = userDetails.getRole();
        List<String> roles = userDetails.getRoles();
        
        log.info("获取到用户 [{}] 角色信息: 主角色={}, 角色列表={}", 
                loginRequest.getUsername(), role, roles);
        
        // 生成令牌
        String accessToken = jwtUtil.generateToken(
                userId, 
                loginRequest.getUsername(), 
                loginRequest.getRememberMe()
        );
        
        // 刷新令牌可以是相同的，实际项目中通常会生成不同的刷新令牌
        String refreshToken = accessToken;
        
        // 计算过期时间
        long expiresIn = loginRequest.getRememberMe() ? 
                3600 * 24 * 7 : 3600; // 7天或1小时
        
        // 构建并返回令牌信息
        TokenInfo tokenInfo = TokenInfo.builder()
                .accessToken(accessToken)
                .refreshToken(refreshToken)
                .tokenType("Bearer")
                .expiresIn(expiresIn)
                .userId(userId)
                .username(loginRequest.getUsername())
                .role(role)  // 添加主要角色
                .roles(roles)  // 添加角色列表
                .build();
        
        log.info("登录成功，已生成令牌: {}", loginRequest.getUsername());
        return Result.success(tokenInfo);
    }
    
    /**
     * 刷新令牌
     *
     * @param refreshToken 刷新令牌
     * @return 新的令牌信息
     */
    @PostMapping("/refresh")
    public Result<TokenInfo> refresh(@RequestBody String refreshToken) {
        log.info("刷新令牌请求");
        
        // 验证刷新令牌
        if (!jwtUtil.validateToken(refreshToken)) {
            log.warn("刷新令牌验证失败");
            throw new BusinessException(ResultCode.TOKEN_EXPIRED);
        }
        
        // 从刷新令牌中获取用户信息
        Long userId = jwtUtil.getUserIdFromToken(refreshToken);
        String username = jwtUtil.getUsernameFromToken(refreshToken);
        
        log.info("刷新令牌验证成功: {}, userId: {}", username, userId);
        
        // 获取用户详情以获取最新的角色信息
        UserDTO userDetails = userServiceClient.getUserDetails(userId);
        String role = userDetails.getRole();
        List<String> roles = userDetails.getRoles();
        
        // 生成新的访问令牌
        String newAccessToken = jwtUtil.generateToken(userId, username, false);
        
        // 构建并返回令牌信息
        TokenInfo tokenInfo = TokenInfo.builder()
                .accessToken(newAccessToken)
                .refreshToken(refreshToken) // 保持原来的刷新令牌
                .tokenType("Bearer")
                .expiresIn(3600L) // 1小时
                .userId(userId)
                .username(username)
                .role(role)  // 添加主要角色
                .roles(roles)  // 添加角色列表
                .build();
        
        log.info("刷新令牌成功: {}", username);
        return Result.success(tokenInfo);
    }
    
    /**
     * 验证令牌
     *
     * @param token 访问令牌
     * @return 验证结果
     */
    @GetMapping("/validate")
    public Result<Boolean> validateToken(@RequestParam("token") String token) {
        log.info("验证令牌请求");
        boolean valid = jwtUtil.validateToken(token);
        log.info("令牌验证结果: {}", valid);
        return Result.success(valid);
    }
    
    /**
     * 获取令牌信息
     *
     * @param token 访问令牌
     * @return 令牌中的用户信息
     */
    @GetMapping("/info")
    public Result<TokenInfo> getTokenInfo(@RequestParam("token") String token) {
        log.info("获取令牌信息请求");
        
        if (!jwtUtil.validateToken(token)) {
            log.warn("令牌验证失败");
            throw new BusinessException(ResultCode.TOKEN_INVALID);
        }
        
        Long userId = jwtUtil.getUserIdFromToken(token);
        String username = jwtUtil.getUsernameFromToken(token);
        long expiresIn = jwtUtil.getRemainingTimeFromToken(token);
        
        // 获取用户详情以获取最新的角色信息
        UserDTO userDetails = userServiceClient.getUserDetails(userId);
        String role = userDetails.getRole();
        List<String> roles = userDetails.getRoles();
        
        TokenInfo tokenInfo = TokenInfo.builder()
                .userId(userId)
                .username(username)
                .expiresIn(expiresIn)
                .role(role)  // 添加主要角色
                .roles(roles)  // 添加角色列表
                .build();
        
        log.info("获取令牌信息成功: {}", username);
        return Result.success(tokenInfo);
    }
} 